﻿#region Header

/*
Measure emotions of a group of person
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

#endregion

namespace Tests.Basics {
	/// <summary>
	/// Description of the classhm...
	/// </summary>
	[TestClass]
	public class TestMaple {
		#region Public Methods

		// When evaluating something Maple will send errors through this function.
		// If not defined, errors will go through the text callback.
		public static void cbError(IntPtr data, IntPtr offset, IntPtr msg) {
			//Console.WriteLine("offset is " + offset.ToInt32() );
			string s = Marshal.PtrToStringAnsi(msg);
			Console.WriteLine(s);
		}

		// When evaluating something Maple will send a message about resources
		// used once per garbage collection.  If you don't want to see these
		// messages, just comment out the WriteLine command inside.
		public static void cbStatus(IntPtr data, IntPtr used, IntPtr alloc, double time) {
			Console.WriteLine("cputime=" + time + "; memory used=" + used.ToInt64() + "kB" + " alloc=" + alloc.ToInt64() +
							   "kB");
		}

		[TestMethod]
		public void TestSimpleCalculationViaMaple() {
			MapleEngine.MapleCallbacks cb;
			var err = new byte[2048];
			IntPtr kv;

			// pass -A2 which sets kernelopts(assertlevel=2) just to show
			// how in this example.  The corresponding argc parameter 
			// (the first argument to StartMaple) should then be 2
			// argv[0] should always be filled in with something.
			var argv = new String[2];
			argv[0] = "maple";
			argv[1] = "-A2";

			// only a textcallback is really needed here, but error and status
			// callbacks are also provided to show how to handle the IntPtr
			// arguments
			cb.textCallBack = delegate(IntPtr data, int tag, IntPtr output) {
				//Console.WriteLine("tag is " + tag );
				string s = Marshal.PtrToStringAnsi(output);
				Assert.AreEqual("50", s);
				Console.WriteLine(s);
			};
			cb.errorCallBack = cbError;
			cb.statusCallBack = cbStatus;
			cb.readlineCallBack = null;
			cb.redirectCallBack = null;
			cb.streamCallBack = null;
			cb.queryInterrupt = null;
			cb.callbackCallBack = null;

			try {
				kv = MapleEngine.StartMaple(2, argv, ref cb, IntPtr.Zero, IntPtr.Zero, err);
			}
			catch (DllNotFoundException e) {
				Console.WriteLine(e.ToString());
				return;
			}
			catch (EntryPointNotFoundException e) {
				Console.WriteLine(e.ToString());
				return;
			}

			// make sure we got a good kernel vector handle back
			if (kv.ToInt64() == 0) {
				// Maple didn't start properly.  The "err" parameter will be filled
				// in with the reason why (usually a license error)
				// Note that since we passed in a byte[] array we need to trim
				// the characters past \0 during conversion to string
				Console.WriteLine("Fatal Error, could not start Maple: {0}",
								   Encoding.ASCII.GetString(err, 0, Array.IndexOf(err, (byte)0)));
				return;
			}

			// set the default plot driver to something nicer than "char"
			MapleEngine.EvalMapleStatement(kv, Encoding.ASCII.GetBytes("plotsetup(maplet):"));
			const string expr = "25+25";

			// This evaluates the inputted expression and sends the text output
			// to the text callback (cbText).  It also returns a handle to the
			// result.  Use a colon to terminate the statement if you don't
			// want any output (a result is still returned).
			MapleEngine.EvalMapleStatement(kv, Encoding.ASCII.GetBytes(expr + ";"));

			MapleEngine.StopMaple(kv);
		}

		#endregion
	}
}